package table

import (
	"encoding/xml"
	"fmt"
	"os"
	"playbook/ginsvr/src/orm"
	"strings"

	"github.com/sirupsen/logrus"
)

type XmlInfo struct {
	SqlType string `json:"sqlType"`
	//ResultMapId string            `json:"resultMapId"`
	ResultMap map[string]string `json:"resultMap"`
	//SqlId       string            `json:"sqlId"`
	Sql string `json:"sql"`
}

type MapperSelect struct {
	XMLName   xml.Name  `xml:"mapper"`
	NameSpace string    `xml:"namespace,attr"`
	ResultMap ResultMap `xml:"resultMap"`
	Sql       Sql       `xml:"select"`
}

type MapperInsert struct {
	XMLName   xml.Name `xml:"mapper"`
	NameSpace string   `xml:"namespace,attr"`
	Sql       Sql      `xml:"insert"`
}

type MapperUpdate struct {
	XMLName   xml.Name `xml:"mapper"`
	NameSpace string   `xml:"namespace,attr"`
	Sql       Sql      `xml:"update"`
}

type MapperDelete struct {
	XMLName   xml.Name `xml:"mapper"`
	NameSpace string   `xml:"namespace,attr"`
	Sql       Sql      `xml:"delete"`
}

type ResultMap struct {
	XMLName xml.Name `xml:"resultMap"`
	Id      string   `xml:"id,attr"`
	Type    string   `xml:"type,attr"`
	Result  []Result `xml:"result"`
}

type Result struct {
	XMLName  xml.Name `xml:"result"`
	Property string   `xml:"property,attr"`
	Column   string   `xml:"column,attr"`
}

type Sql struct {
	Id            string `xml:"id,attr"`
	ParameterType string `xml:"parameterType,attr"`
	ResultMap     string `xml:"resultMap,attr,omitempty"`
	Content       string `xml:",chardata"`
}

func GenerateXML(xmlInfo XmlInfo, atomName string, atomId string) error {
	atomSvrDefine := orm.GetAtomSvrDefbyId(atomId)
	paramRelationOut, _ := orm.GetParameterbyId(atomSvrDefine.Outputparamid, "")
	outSubParam := orm.GetParamById(paramRelationOut[0].Subparamid)
	inParam := orm.GetParamById(atomSvrDefine.Inputparamid)
	var outSubParam2 orm.Parameter
	if "List" == outSubParam.Classpath {
		paramRelationOut2, _ := orm.GetParameterbyId(outSubParam.Parameterid, "")
		outSubParam2 = orm.GetParamById(paramRelationOut2[0].Subparamid)
	}
	var mapper interface{}
	mapperHeader := "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n "
	sql := &Sql{
		Id:            strings.ToLower(xmlInfo.SqlType),
		ParameterType: inParam.Classpath,
		Content:       xmlInfo.Sql,
	}
	switch xmlInfo.SqlType {
	case "SELECT":
		resultMap := &ResultMap{
			Id:   "ResultMap",
			Type: getModelType(outSubParam, outSubParam2),
		}
		for column, property := range xmlInfo.ResultMap {
			resultMap.Result = append(resultMap.Result, Result{
				Property: getProperty(property),
				Column:   column,
			})
		}
		sql.ResultMap = "ResultMap"
		mapperSelect := &MapperSelect{
			NameSpace: buildMapperClassPath(atomName),
			ResultMap: *resultMap,
			Sql:       *sql,
		}
		mapper = mapperSelect
	case "INSERT":
		mapperInsert := &MapperInsert{
			NameSpace: buildMapperClassPath(atomName),
			Sql:       *sql,
		}
		mapper = mapperInsert
	case "UPDATE":
		mapperUpdate := &MapperUpdate{
			NameSpace: buildMapperClassPath(atomName),
			Sql:       *sql,
		}
		mapper = mapperUpdate
	case "DELETE":
		mapperDelete := &MapperDelete{
			NameSpace: buildMapperClassPath(atomName),
			Sql:       *sql,
		}
		mapper = mapperDelete
	}

	output, err := xml.MarshalIndent(mapper, "", "    ")
	if err != nil {
		fmt.Println(err)
		return err
	}

	xmlPath := buildMapperPath(atomName)
	err = os.MkdirAll(xmlPath[:strings.LastIndex(xmlPath, "\\")], os.ModePerm)
	if err != nil {
		logrus.Error(err.Error())
		return err
	}

	dstFile, err := os.Create(xmlPath)
	if err != nil {
		logrus.Error("创建文件失败")
		return err
	}
	defer dstFile.Close()
	dstFile.WriteString(mapperHeader)
	dstFile.Write(output)
	return nil
}

func getModelType(param1 orm.Parameter, param2 orm.Parameter) string {
	if "List" == param1.Classpath {
		return param2.Classpath
	}
	return param1.Classpath
}

func getProperty(property string) string {
	if property == "" {
		return property
	}
	arr := strings.Split(property, ".")
	return arr[len(arr)-1]
}

func buildMapperPath(atomName string) string {
	localPath := orm.GetLocalPath("00001")
	gsd := orm.GetGeneSrcDefine("mapperXml")
	var sb strings.Builder
	sb.WriteString(localPath.LocalPath)
	sb.WriteString("\\")
	sb.WriteString(gsd.Srcpath)
	sb.WriteString("\\")
	sb.WriteString(atomName)
	sb.WriteString(".xml")
	return sb.String()
}

func buildMapperClassPath(atomName string) string {
	gsd := orm.GetGeneSrcDefine("mapper")
	var srcPath = gsd.Srcpath
	var packageName = srcPath[strings.Index(srcPath, "java")+5:]
	packageName = strings.ReplaceAll(packageName, "\\", ".")
	return packageName + "." + atomName + "Mapper"
}
